require 'rake/clean'

PROJECT = "mlisp"
EXE_FILE = "#{PROJECT}.exe"

OBJ_PATH = "obj"
OBJ_EXT = ".o"

INC_PATHS = %w(src/sexp)
INCLUDES = INC_PATHS.map {|x| "-I#{x}"}.join(" ")

C_OPT = "#{INCLUDES} -O2 -DWIN32"
CC = "gcc #{C_OPT} -c"

LINK_OPT = ""
LINK = "gcc"

####

# Load gcc depend file.
def load_depend(fn)
	h = {}
	File.open(fn) do |f|
		while f.gets
			line = $_.chomp
			while line =~ /\\$/
				line = Regexp.last_match.pre_match + f.gets.chomp
			end

			if line =~ /^([^:]+):\s*(.*)$/
				key = $1
				srcs = $2.split(/\s+/)
				h[key] = srcs
			end
		end
	end
	h
end

####

SRCS = FileList["src/sexp/*.c"] + FileList["src/mlisp/*.c"] + FileList["src/mlisp/*.cpp"]
HEADERS = FileList["src/sexp/*.h"] + FileList["src/mlisp/*.h"]
OBJS = SRCS.ext(OBJ_EXT).collect {|item| "#{OBJ_PATH}/#{File.basename(item)}"}

# find source from target file name
def find_depend
	lambda do |target_name|
		unless $depend
			unless File.exist?("depend")
				sh "rake depend"
			end
			$depend = load_depend("depend")
		end

		base = File.basename(target_name)
		$depend[base]
	end
end

# rule: obj for src
rule /.#{OBJ_EXT}$/ => [find_depend(), OBJ_PATH, "depend"] do |t|
	sh "#{CC} -o#{t.name} #{t.source}"
end

CLEAN.include(OBJS, OBJ_PATH, EXE_FILE, "depend")

task :clean do
	cd "test" do
		sh "rake clean"
	end
end

desc "Build exe file (default)"
task :default => EXE_FILE

file EXE_FILE => OBJS do |t|
	sh "#{LINK} -o#{t.name} #{t.prerequisites.join(' ')} #{LINK_OPT}"
end

directory OBJ_PATH

desc "Count source files and total lines"
task "count" do
	sh %!echo #{SRCS} #{HEADERS} | wc | gawk '{print $2 " files (.c, .h, .cpp)"}'!
	sh %!echo #{SRCS} #{HEADERS} | xargs cat | wc | gawk '{print $1 " lines"}'!
end

desc "Check source size"
task "size" do
	sh %!echo #{SRCS} | xargs wc | sort -r!
end


task "test" do
	cd "test" do
		sh "rake default check"
	end
end




file "depend" do
	sh "#{CC} -MM #{SRCS} > depend"
end
